package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper,OrderInfo> implements OrderService {

    @Value("${ware.url}")
    private String wareUrl;


    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    @Override
    public String getTradeNo(String userId) {
        String tradeNo = UUID.randomUUID().toString();

        String tradeNoKey = "tradeNo:" + userId;
        redisTemplate.opsForValue().set(tradeNoKey, tradeNo);

        return tradeNo;
    }

    @Override
    public Boolean checkTradeNo(String tradeNo, String userId) {
        String tradeNoKey = "tradeNo:" +userId;
        String  redisTradeNo = (String) redisTemplate.opsForValue().get(tradeNoKey);
        return tradeNo.equals(redisTradeNo);
    }

    @Override
    public Boolean checkStock(Long skuId, Integer skuNum) {
        String result = HttpClientUtil.doGet(wareUrl + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
        //  判断返回
        return "1".equals(result);
    }

    @Override
    public void delTradeNo(String userId) {
        redisTemplate.delete("tradeNo:"+userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveOrderInfo(OrderInfo orderInfo) {

        orderInfo.sumTotalAmount();
        //设置支付状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());

        //交易号不能重复
        String outTradeNo = "atguigu"+ System.currentTimeMillis()+"" +new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //  把订单明细中的各个商品名称拼接起来。
        orderInfo.setTradeBody("购买小分队.....");
        orderInfo.setOperateTime(new Date());
        //  设置过期时间：
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,1);
        orderInfo.setExpireTime(calendar.getTime());
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        orderInfoMapper.insert(orderInfo);

        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        Long orderId = orderInfo.getId();
        if (!CollectionUtils.isEmpty(orderDetailList)) {
            for (OrderDetail orderDetail : orderDetailList) {
                orderDetail.setOrderId(orderId);
                orderDetailMapper.insert(orderDetail);
            }
        }
        //发送延迟消息 3秒不支付取消
        this.rabbitService.sendDelayMsg(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,MqConst.ROUTING_ORDER_CANCEL,orderId,MqConst.DELAY_TIME);
        return orderId;
    }

    @Override
    public IPage getOrderList(Page<OrderInfo> orderInfoPage, String userId) {
        IPage<OrderInfo> iPage = orderInfoMapper.selectOrderList(orderInfoPage,userId);
        iPage.getRecords().forEach(page->{
            page.setOrderStatusName(OrderStatus.getStatusNameByStatus(page.getOrderStatus()));
        });
        return iPage;
    }

    @Override
    public void execExpiredOrder(Long orderId) {
        this.updateOrderStatus(orderId,ProcessStatus.CLOSED);

        //  应该判断：是否有paymentInfo .

        //  发送消息关闭paymentInfo
        this.rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);
    }

    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        //更新订单状态
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        //更新订单进度状态
        orderInfo.setProcessStatus(processStatus.name());

        orderInfoMapper.updateById(orderInfo);
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (orderInfo!= null){
            QueryWrapper<OrderDetail> orderDetailQueryWrapper = new QueryWrapper<>();
            orderDetailQueryWrapper.eq("order_id",orderId);
            orderInfo.setOrderDetailList(orderDetailMapper.selectList(orderDetailQueryWrapper));
        }
        return orderInfo;
    }

    @Override
    public void sendOrderStatus(Long orderId) {
        this.updateOrderStatus(orderId,ProcessStatus.NOTIFIED_WARE);
        //  组装发送消息的内容.
        OrderInfo orderInfo = this.getOrderInfo(orderId);

        //  将orderInfo 中的部分数据转换为map,再转换为Json 数据发送出去.
            Map map = this.initWare(orderInfo);

        this.rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,MqConst.ROUTING_WARE_STOCK, JSON.toJSONString(map));
//        this.rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,MqConst.ROUTING_WARE_STOCK, JSON.toJSON(map));
    }

    @Override
    public Map initWare(OrderInfo orderInfo) {

        HashMap<String, Object> map = new HashMap<>();

        map.put("order_id",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel",orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "2");
        map.put("wareId", orderInfo.getWareId());


        List<HashMap<String, Object>> maps = orderInfo.getOrderDetailList().stream().map(orderDetail -> {
            HashMap<String, Object> detailMap = new HashMap<>();
            detailMap.put("skuId",orderDetail.getSkuId());
            detailMap.put("skuName",orderDetail.getSkuName());
            detailMap.put("skuNum",orderDetail.getSkuNum());
            return detailMap;
        }).collect(Collectors.toList());
        map.put("details",maps);
        return map;
    }


    @Override
    public List<OrderInfo> orderSplit(String orderId, String wareSkuMap) {
        /*
        1.  先获取到原始订单。  orderId
        2.  wareSkuMap 存储的是仓库Id 与 skuId 的对照关系！
            [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]  List<Map>
            需要将这个参数变为可以操作的对象 例如 map class 等.
        3.  创建新的子订单对象 并赋值
        4.  保存好子订单， 订单的状态不需要手动更改，只需要支付成功之后，通过mq 发送消息的形式 ，自动更改状态.
        5.  将子订单保存到集合中
        6.  修改原始订单状态. SPLIT;
        7.  测试.

         */


        OrderInfo originOrderInfo = this.getOrderInfo(Long.parseLong(orderId));
        //声明一个集合
        List<OrderInfo> subOrderInfoList = new ArrayList<>();
        //数据转换
        List<Map> mapList = JSON.parseArray(wareSkuMap, Map.class);
        //判断
        if (!CollectionUtils.isEmpty(mapList)) {
            for (Map map : mapList) {
                //得到仓库id
                String wareId = (String) map.get("wareId");
                List<String> skuIdList = (List<String>) map.get("skuIds");
                //创建子订单 并赋值
                OrderInfo subOrderInfo = new OrderInfo();
                BeanUtils.copyProperties(originOrderInfo,subOrderInfo);
                //id设置为空
                subOrderInfo.setId(null);
                //父id
                subOrderInfo.setParentOrderId(Long.parseLong(orderId));
                //仓库id
                subOrderInfo.setWareId(wareId);

                //  计算每个子订单的总金额
                List<OrderDetail> orderDetails = new ArrayList<>();
                List<OrderDetail> orderDetailList = originOrderInfo.getOrderDetailList();
                for (OrderDetail orderDetail : orderDetailList) {
                    for (String skuId : skuIdList) {
                        if (orderDetail.getSkuId()==Long.parseLong(skuId)){

                            orderDetails.add(orderDetail);
                        }
                    }
                }
                subOrderInfo.setOrderDetailList(orderDetails);
                subOrderInfo.sumTotalAmount();
                //  保存子订单：
                this.saveOrderInfo(subOrderInfo);
                //  将子订单添加到集合中
                subOrderInfoList.add(subOrderInfo);
            }
        }
        this.updateOrderStatus(Long.parseLong(orderId),ProcessStatus.SPLIT);
        return subOrderInfoList;
    }

    @Override
    public void execExpiredOrder(Long orderId, String flag) {
        updateOrderStatus(orderId,ProcessStatus.CLOSED);

        if ("2".equals(flag)){
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);
        }
    }
}
